load("@rules_proto//proto:defs.bzl", "proto_library")
load("@io_bazel_rules_rust//rust:rust.bzl", "rust_binary", "rust_library", "rust_test")
load("@io_bazel_rules_rust//cargo:cargo_build_script.bzl", "cargo_build_script")
load(":rustfmt.bzl", "rustfmt_fix", "rustfmt_test")
load(":clang_format.bzl", "proto_format")
load("//ts:sql_format.bzl", "sql_format")

# Build script
#######################

cargo_build_script(
    name = "build_script",
    srcs = glob(["build/*.rs"]),
    build_script_env = {
        "BACKEND_PROTO": "$(location backend.proto)",
        "PROTOC": "$(location @com_google_protobuf//:protoc)",
        "RSLIB_FTL_ROOT": "$(location @rslib_ftl//:l10n.toml)",
        "EXTRA_FTL_ROOT": "$(location @extra_ftl//:l10n.toml)",
        "BAZEL": "1",
    },
    crate_root = "build/main.rs",
    data = [
        "//ftl",
        "backend.proto",
        "@com_google_protobuf//:protoc",
        # bazel requires us to list these out separately
        "@rslib_ftl//:l10n.toml",
        "@extra_ftl//:l10n.toml",
    ],
    deps = [
        "//rslib/cargo:fluent_syntax",
        "//rslib/cargo:prost_build",
    ],
)

# Library
#######################

_anki_compile_data = glob([
    "src/**/*.sql",
    "src/**/*.html",
    "src/**/*.css",
    "src/**/*.tex",
]) + [
    "Cargo.toml",  # prevents a warning about num_enum
    "//:buildinfo.txt",
    "templates/.empty",  # required for askama
]

_anki_features = [
    "translations",
]

_anki_rustc_env = {
    "BUILDINFO": "$(location //:buildinfo.txt)",
}

rust_library(
    name = "anki",
    srcs = glob([
        "src/**/*.rs",
    ]),
    compile_data = _anki_compile_data,
    crate_features = _anki_features,
    proc_macro_deps = [
        "//rslib/cargo:serde_derive",
        "//rslib/cargo:serde_repr",
        "//rslib/cargo:async_trait",
    ],
    rustc_env = _anki_rustc_env,
    visibility = ["//visibility:public"],
    deps = [
        ":build_script",
        "//rslib/cargo:askama",
        "//rslib/cargo:async_compression",
        "//rslib/cargo:blake3",
        "//rslib/cargo:bytes",
        "//rslib/cargo:chrono",
        "//rslib/cargo:coarsetime",
        "//rslib/cargo:failure",
        "//rslib/cargo:flate2",
        "//rslib/cargo:fluent",
        "//rslib/cargo:futures",
        "//rslib/cargo:hex",
        "//rslib/cargo:htmlescape",
        "//rslib/cargo:intl_memoizer",
        "//rslib/cargo:itertools",
        "//rslib/cargo:lazy_static",
        "//rslib/cargo:nom",
        "//rslib/cargo:num_enum",
        "//rslib/cargo:num_format",
        "//rslib/cargo:num_integer",
        "//rslib/cargo:once_cell",
        "//rslib/cargo:pin_project",
        "//rslib/cargo:prost",
        "//rslib/cargo:rand",
        "//rslib/cargo:regex",
        "//rslib/cargo:reqwest",
        "//rslib/cargo:rusqlite",
        "//rslib/cargo:scopeguard",
        "//rslib/cargo:serde",
        "//rslib/cargo:serde_aux",
        "//rslib/cargo:serde_json",
        "//rslib/cargo:serde_tuple",
        "//rslib/cargo:sha1",
        "//rslib/cargo:slog",
        "//rslib/cargo:slog_async",
        "//rslib/cargo:slog_envlogger",
        "//rslib/cargo:slog_term",
        "//rslib/cargo:tempfile",
        "//rslib/cargo:tokio",
        "//rslib/cargo:unic_langid",
        "//rslib/cargo:unicase",
        "//rslib/cargo:unicode_normalization",
        "//rslib/cargo:utime",
        "//rslib/cargo:zip",
    ],
)

# Tests
#######################

rust_test(
    name = "unit_tests",
    compile_data = _anki_compile_data,
    crate = ":anki",
    crate_features = _anki_features,
    data = glob([
        "tests/support/**",
    ]),
    rustc_env = _anki_rustc_env,
    deps = ["//rslib/cargo:env_logger"],
)

rustfmt_test(
    name = "format_check",
    srcs = glob([
        "src/**/*.rs",
    ]),
)

rustfmt_fix(
    name = "format",
    srcs = glob([
        "src/**/*.rs",
    ]),
)

sql_format(
    name = "sql_format",
    srcs = glob(["**/*.sql"]),
)

proto_format(
    name = "proto_format",
    srcs = ["backend.proto"],
)

# fluent.proto generation
###########################
# This separate step is required to make the file available to downstream consumers.

rust_binary(
    name = "write_fluent_proto",
    srcs = [
        "build/mergeftl.rs",
        "build/write_fluent_proto.rs",
    ],
    deps = ["//rslib/cargo:fluent_syntax"],
)

genrule(
    name = "fluent_proto",
    srcs = [
        "//ftl",
        "//ftl:BUILD.bazel",
        "//rslib/cargo:fluent_syntax",
        "@rslib_ftl//:l10n.toml",
        "@extra_ftl//:l10n.toml",
    ],
    outs = ["fluent.proto"],
    cmd = """\
RSLIB_FTL_ROOT="$(location @rslib_ftl//:l10n.toml)" \
EXTRA_FTL_ROOT="$(location @extra_ftl//:l10n.toml)" \
FTL_SRC="$(location //ftl:BUILD.bazel)" \
$(location :write_fluent_proto) $(location fluent.proto)""",
    tools = [
        ":write_fluent_proto",
    ],
    visibility = ["//visibility:public"],
)

proto_library(
    name = "fluent_proto_lib",
    srcs = ["fluent.proto"],
    visibility = ["//visibility:public"],
)

proto_library(
    name = "backend_proto_lib",
    srcs = ["backend.proto"],
    visibility = ["//visibility:public"],
)

exports_files(["backend.proto"])
